package com.javasm.process.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.unit.DataUnit;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.Update;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.javasm.commons.enums.E;
import com.javasm.commons.exceptions.MvcException;
import com.javasm.process.ProcessService;
import com.javasm.process.entity.ProcessDef;
import com.javasm.process.entity.ProcessTask;
import com.javasm.process.entity.TaskStatus;
import com.javasm.process.service.ProcessDefService;
import com.javasm.process.service.ProcessTaskService;
import com.javasm.sys.SysUser;
import com.javasm.sys.UserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ProcessServiceImpl implements ProcessService {
    @Resource
    private ProcessDefService defService;
    @Resource
    private ProcessTaskService taskService;
    @Resource
    private UserService userService;

    @Override
    public boolean startProcess(String defName, String applyId) {
        //defService 查找下一步审批人部门和职务
        Integer pleveal = 0;
        ProcessDef nextDef = defService.getNextDef(defName,pleveal);
        List<SysUser> users = userService.getUserByDeptAndPosition(nextDef.getTaskUserDept(),nextDef.getTaskUserPosition());
        if(users.size()==0)return false;
        boolean autoClaim=false;
        if(users.size()==1)autoClaim=true;
        for (SysUser user : users) {
            //cpts 添加待审核的记录
            ProcessTask task = new ProcessTask();
            task.setApplyId(applyId);
            task.setProcessName(defName);
            task.setTaskName(nextDef.getTaskName());
            task.setTaskUser(user.getUserName());
            task.setTaskBegin(DateUtil.now());
            if(autoClaim)
                task.setClaimTime(DateUtil.now());
            taskService.save(task);
        }
        return true;
    }

    @Override//查询待办任务
    public List<ProcessTask> queryToDoTasks(String defName, String loginUser) {
        QueryWrapper w = new QueryWrapper();
        w.eq("process_name",defName);
        w.eq("task_user",loginUser);
        w.isNull("task_end");
        List<ProcessTask> list = taskService.list(w);
        return list;
    }

    @Override//查询通过或为通过的已办任务
    public List<ProcessTask> queryDosTasks(String defName, String loginuser, String result) {
        QueryWrapper w = new QueryWrapper();
        w.eq("process_name",defName);
        w.eq("task_user",loginuser);
        w.isNotNull("task_end");
        if (StrUtil.isNotEmpty(result)){
            w.eq("approve_result",result);
        }
        List<ProcessTask> list = taskService.list(w);
        return list;
    }

    @Override
    public List<ProcessTask> getTaskByApplyOrderId(String defName, String orderId) {
        QueryWrapper w = new QueryWrapper();
        w.eq("process_name",defName);
        w.eq("apply_id",orderId);
        w.orderByAsc("claim_time");
        return taskService.list(w);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String approve(String defName, ProcessTask task, String loginuser) {
        String approveResult = task.getApproveResult();
        if (null == approveResult) return null;
        if (TaskStatus.APPROVE_WTG.getStatus().equals(approveResult)){
            taskService.endTask(defName,task,loginuser);
            //要回传数据，更新申请单通过的状态(未通过)
            return task.getApproveResult();
        }else if (TaskStatus.APPROVE_TG.getStatus().equals(approveResult)){
            //当前任务要完成
            taskService.endTask(defName,task,loginuser);
            //根据当前审批人的部门、职务、defName查询当前任务所处的leveal
            ProcessDef currentDef = defService.getCurrentDef(defName,task.getTaskName());
            ProcessDef next = defService.getNextDef(defName, currentDef.getTaskLeveal());
            if (next != null){
                //cus 根据部门和职务查找id
                List<SysUser> users = userService.getUserByDeptAndPosition(next.getTaskUserDept(),next.getTaskUserPosition());
                if(users.size()==0)throw new MvcException(E.ERROR);
                boolean autoClaim=false;
                if(users.size()==1)autoClaim=true;
                for (SysUser user : users) {
                    ProcessTask processTask = new ProcessTask();
                    processTask.setApplyId(task.getApplyId());
                    processTask.setProcessName(defName);
                    processTask.setTaskName(next.getTaskName());
                    processTask.setTaskUser(user.getUserName());
                    processTask.setTaskBegin(DateUtil.now());
                    if(autoClaim)
                        processTask.setClaimTime(DateUtil.now());
                    taskService.save(processTask);
                }
                return null;
            } else {
                return task.getApproveResult();
            }
        }
        return null;
    }

    @Transactional
    @Override
    public Boolean claim(String loginuser, ProcessTask task) {
        String id = task.getId();
        String applyId = task.getApplyId();
        String taskName = task.getTaskName();

        if(StrUtil.isEmpty(id)||StrUtil.isEmpty(applyId)||StrUtil.isEmpty(taskName))return false;

        UpdateWrapper w = new UpdateWrapper();
        w.eq("id",id);
        w.eq("task_user",loginuser);
        w.set("claim_time",DateUtil.now());
        boolean isok = taskService.update(w);

        QueryWrapper w2 = new QueryWrapper();
        w2.eq("apply_id",applyId);
        w2.eq("task_name",taskName);
        w2.isNull("claim_time");
        w2.ne("task_user",loginuser);
        taskService.remove(w2);

        return isok;
    }

    @Override
    public List<String> listTodoApplyIds(String defName, String loginUserName) {
        List<ProcessTask> processTasks = queryToDoTasks(defName, loginUserName);
        if(processTasks==null||processTasks.size()==0)return Collections.emptyList();
        return processTasks.stream().map(ProcessTask::getApplyId).collect(Collectors.toList());
    }

    @Override
    public List<String> listdoApplyIds(String defName, String loginUserName, String status) {
        List<ProcessTask> processTasks = queryDosTasks(defName, loginUserName, status);
        if(processTasks==null||processTasks.size()==0)return Collections.emptyList();
        return processTasks.stream().map(ProcessTask::getApplyId).collect(Collectors.toList());
    }

    @Transactional
    @Override
    public Boolean claim(String loginuser, String orderId) {
        QueryWrapper w = new QueryWrapper();
        w.isNull("task_end");
        w.isNull("claim_time");
        w.eq("apply_id",orderId);
        List<ProcessTask> list = taskService.list(w);
        Iterator<ProcessTask> iterator = list.iterator();
        while(iterator.hasNext()){
            ProcessTask t = iterator.next();
            String taskUser = t.getTaskUser();
            if(taskUser.equals(loginuser)){
                t.setClaimTime(DateUtil.now());
                taskService.updateById(t);
            }else{
                taskService.removeById(t.getId());
            }
        }
        return true;
    }
}
